//#include "bsp.h"
#include "modbus_slave.h"
//#include "main.h"
#include "crc16.h"
#include "board.h"
#include "bsp_user_lib.h"
#include "bsp_usart.h"

//寄存器状态  第一位表示可写，第二位表示可读，使用逻辑判断控制
#define WO 		1	//只写  	01
#define RO 		2	//只读  	10
#define RW 		3	//可读写	11
//寄存器数据地址
#define RADD 	0	//寄存器地址
#define RAW 	1	//寄存器可读写性
#define RDATA	2	//对应数据




uint16_t ModbusReg[][3]={
{	MReg0	,	RO	,	0	},	//	第0位方便对位，不使用
{	MReg_Power	,	RW	,	0	},	//	读写器功率，0-33dBm
{	MReg_CardNum	,	RW	,	0	},	//	读取到的卡片数量
{	MReg_CardMaxCount	,	RW	,	0	},	//	最多次数的卡片的次数
{	MReg_CardMax1	,	RO	,	0	},	//	最大的卡片EPC第1个字
{	MReg_CardMax2	,	RO	,	0	},	//	最大的卡片EPC第2个字
{	MReg_CardMax3	,	RO	,	0	},	//	最大的卡片EPC第3个字
{	MReg_CardMax4	,	RO	,	0	},	//	最大的卡片EPC第4个字
{	MReg_CardMax5	,	RO	,	0	},	//	最大的卡片EPC第5个字
{	MReg_CardMax6	,	RO	,	0	},	//	最大的卡片EPC第6个字
{	MReg_CardMax7	,	RO	,	0	},	//	最大的卡片EPC第7个字
{	MReg_CardMax8	,	RO	,	0	},	//	最大的卡片EPC第8个字
{	MReg_CardMax9	,	RO	,	0	},	//	最大的卡片EPC第9个字
{	MReg_CardMax10	,	RO	,	0	},	//	最大的卡片EPC第10个字

};

extern  _Main_t mainPar;;
extern _Sys_t  Sys;

static void MODS_SendWithCRC(uint8_t *_pBuf, uint8_t _ucLen);
static void MODS_SendAckOk(void);
static void MODS_SendAckErr(uint8_t _ucErrCode);

static void MODS_AnalyzeApp(void);

static void MODS_RxTimeOut(void);

static void MODS_01H(void);
static void MODS_02H(void);
static void All_MODS_03H(void);
static void MODS_03H(void);
static void MODS_04H(void);
static void MODS_41H(void);
static void MODS_42H(void);
static void MODS_43H(void);
static void MODS_47H(void);
static void MODS_05H(void);
static void MODS_06H(void);
static void MODS_10H(void);

static uint8_t AllMODS_ReadRegValue(uint16_t reg_addr, uint8_t *reg_value);
static uint8_t MODS_ReadRegValue(uint16_t reg_addr, uint8_t *reg_value);
static uint8_t MODS_WriteRegValue(uint16_t reg_addr, uint16_t reg_value);

static uint8_t g_mods_timeout = 0;
void MODS_ReciveNew(uint8_t _byte);

MODS_T g_tModS;
VAR_T g_tVar;

/*
*********************************************************************************************************
*	函 数 名: MODS_Poll
*	功能说明: 解析数据包. 在主程序中轮流调用。
*	形    参: 无
*	返 回 值: 无
*********************************************************************************************************
*/
void MODS_Poll(void)
{
//	uint8_t CRC_L;
//	uint8_t CRC_H;
	
	uint16_t addr;
	uint16_t crc1;
//	uint16_t CRCS;

	//每次接受到数据的时候会将该变量清空，达到间隔接受数据的作用
	if(g_mods_timeout == 0){g_tModS.RxCount = 0;return;}
	
	g_mods_timeout ++;
	
	if(g_mods_timeout <= 2)return;
		
	g_mods_timeout = 0;
	
	if (g_tModS.RxCount < 4)				/* 接收到的数据小于4个字节就认为错误 */
	{
		goto err_ret;
	}
	
//	printf("g_tModS.RxCount:%d\r\n",g_tModS.RxCount);
	/* 计算CRC校验和 */
	crc1 = CRC16_Modbus(g_tModS.RxBuf, g_tModS.RxCount);
	
	if (crc1 != 0)
	{
		goto err_ret;
	}

	/* 站地址 (1字节） */
	addr = g_tModS.RxBuf[0];				/* 第6字节 站号 */
//	rt_kprintf("crc1=0X%X\r\n",crc1);
	if ((addr != mainPar.deviceAdd)&&(addr != 0xff))		 			/* 判断主机发送的命令地址是否符合如果是广播地址也可以通过 */
	{
		goto err_ret;
	}

	
	MODS_AnalyzeApp();						
	
err_ret:
#if 0										/* 此部分为了串口打印结果,实际运用中可不要 */
	g_tPrint.Rxlen = g_tModS.RxCount;
	memcpy(g_tPrint.RxBuf, g_tModS.RxBuf, g_tModS.RxCount);
#endif
	
	g_tModS.RxCount = 0;					/* 必须清零计数器，方便下次帧同步 */
	
}

/*
*********************************************************************************************************
*	函 数 名: MODS_ReciveNew
*	功能说明: 串口接收中断服务程序会调用本函数。当收到一个字节时，执行一次本函数。
*	形    参: 无
*	返 回 值: 无
*********************************************************************************************************
*/
void MODS_ReciveNew(uint8_t _byte)
{
	/*
		3.5个字符的时间间隔，只是用在RTU模式下面，因为RTU模式没有开始符和结束符，
		两个数据包之间只能靠时间间隔来区分，Modbus定义在不同的波特率下，间隔时间是不一样的，
		所以就是3.5个字符的时间，波特率高，这个时间间隔就小，波特率低，这个时间间隔相应就大

		4800  = 7.297ms
		9600  = 3.646ms
		19200  = 1.771ms
		38400  = 0.885ms
	*/
//	uint32_t timeout;
	
	//定时器开始计数
	g_mods_timeout = 1;
	
//	timeout = 350000 / SBAUD485;			/* 计算超时时间，单位us 35000000*/

	//暂时先不使用间隔符
	/* 硬件定时中断，定时精度us 硬件定时器1用于ADC, 定时器2用于Modbus */
//	bsp_StartHardTimer(1, timeout, (void *)MODS_RxTimeOut);
	
	if (g_tModS.RxCount < S_RX_BUF_SIZE)
	{
		g_tModS.RxBuf[g_tModS.RxCount++] = _byte;
	}
}

/*
*********************************************************************************************************
*	函 数 名: MODS_RxTimeOut
*	功能说明: 超过3.5个字符时间后执行本函数。 设置全局变量 g_mods_timeout = 1; 通知主程序开始解码。
*	形    参: 无
*	返 回 值: 无
*********************************************************************************************************
*/
static void MODS_RxTimeOut(void)
{
	g_mods_timeout = 1;
}

/*
*********************************************************************************************************
*	函 数 名: MODS_SendWithCRC
*	功能说明: 发送一串数据, 自动追加2字节CRC
*	形    参: _pBuf 数据；
*			  _ucLen 数据长度（不带CRC）
*	返 回 值: 无
*********************************************************************************************************
*/
static void MODS_SendWithCRC(uint8_t *_pBuf, uint8_t _ucLen)
{
	uint16_t crc;
	uint8_t buf[S_TX_BUF_SIZE];

	memcpy(buf, _pBuf, _ucLen);
	crc = CRC16_Modbus(_pBuf, _ucLen);
	buf[_ucLen++] = crc >> 8;
	buf[_ucLen++] = crc;
//	printf_x(buf,_ucLen,10);
//	GpioSet(RS485_EN,1);
	USART2_DataSend(buf,_ucLen);
//	GpioSet(RS485_EN,0);
#if 0									/* 此部分为了串口打印结果,实际运用中可不要 */
	g_tPrint.Txlen = _ucLen;
	memcpy(g_tPrint.TxBuf, buf, _ucLen);
#endif
}

/*
*********************************************************************************************************
*	函 数 名: MODS_SendAckErr
*	功能说明: 发送错误应答
*	形    参: _ucErrCode : 错误代码
*	返 回 值: 无
*********************************************************************************************************
*/
static void MODS_SendAckErr(uint8_t _ucErrCode)
{
	uint8_t txbuf[3];

	txbuf[0] = g_tModS.RxBuf[0];					
	txbuf[1] = g_tModS.RxBuf[1]+0x80;		
	txbuf[2] = _ucErrCode;			

	MODS_SendWithCRC(txbuf, 3);
}

/*
*********************************************************************************************************
*	函 数 名: MODS_SendAckOk
*	功能说明: 发送正确的应答.
*	形    参: 无
*	返 回 值: 无
*********************************************************************************************************
*/
static void MODS_SendAckOk(void)
{
	uint8_t txbuf[6];
	uint8_t i;

	for (i = 0; i < 6; i++)
	{
		txbuf[i] = g_tModS.RxBuf[i];
	}
	MODS_SendWithCRC(txbuf, 6);
}

/*
*********************************************************************************************************
*	函 数 名: MODS_AnalyzeApp
*	功能说明: 分析应用层协议
*	形    参: 无
*	返 回 值: 无
*********************************************************************************************************
*/
static void MODS_AnalyzeApp(void)
{
	//广播消息的处理，0xf8为广播地址
	if(g_tModS.RxBuf[0] == 0xff)
	{
		switch(g_tModS.RxBuf[1])
		{
		case 0x03:							/* 广播命令仅允许修改地址*/
			MODS_03H();
			break;
		case 0x06:							/* 广播命令仅允许修改地址*/
			MODS_06H();
			break;
		default:
			g_tModS.RspCode = RSP_ERR_CMD;
			MODS_SendAckErr(g_tModS.RspCode);	/* 告诉主机命令错误 */
			break;	
		}
	}
	else {
		//单独设备的消息处理
		switch (g_tModS.RxBuf[1])				/* 第2个字节 功能码 */
		{		
			case 0x03:							/* 读取多个保持寄存器*/
				MODS_03H();
				break;
			
			case 0x06:							/* 写单个保持寄存器*/
				MODS_06H();
				break;
					
			case 0x10:							/* 写入多个保持寄存器*/
				MODS_10H();
				break;

						
			default:
				g_tModS.RspCode = RSP_ERR_CMD;
				MODS_SendAckErr(g_tModS.RspCode);	/* 告诉主机命令错误 */
				break;
		}
	}
}

/*
*********************************************************************************************************
*	函 数 名: MODS_01H
*	功能说明: 读取线圈状态（对应远程开关D01/D02/D03）
*	形    参: 无
*	返 回 值: 无
*********************************************************************************************************
*/
/* 说明:这里用LED代替继电器,便于观察现象 */
static void MODS_01H(void)
{
	/*
	 举例：
		主机发送:
			11 从机地址
			01 功能码
			00 寄存器起始地址高字节
			13 寄存器起始地址低字节
			00 寄存器数量高字节
			25 寄存器数量低字节
			0E CRC校验高字节
			84 CRC校验低字节

		从机应答: 	1代表ON，0代表OFF。若返回的线圈数不为8的倍数，则在最后数据字节未尾使用0代替. BIT0对应第1个
			11 从机地址
			01 功能码
			05 返回字节数
			CD 数据1(线圈0013H-线圈001AH)
			6B 数据2(线圈001BH-线圈0022H)
			B2 数据3(线圈0023H-线圈002AH)
			0E 数据4(线圈0032H-线圈002BH)
			1B 数据5(线圈0037H-线圈0033H)
			45 CRC校验高字节
			E6 CRC校验低字节

		例子:
			01 01 10 01 00 03   29 0B	--- 查询D01开始的3个继电器状态
			01 01 10 03 00 01   09 0A   --- 查询D03继电器的状态
			
	*/
	uint16_t reg;
	uint16_t num;
	uint16_t i;
	uint16_t m;
	uint8_t status[10];
	
	g_tModS.RspCode = RSP_OK;

	/* 没有外部继电器，直接应答错误 */
	if (g_tModS.RxCount != 8)
	{
		g_tModS.RspCode = RSP_ERR_VALUE;				/* 数据值域错误 */
		return;
	}

	reg = BEBufToUint16(&g_tModS.RxBuf[2]); 			/* 寄存器号 */
	num = BEBufToUint16(&g_tModS.RxBuf[4]);				/* 寄存器个数 */

	m = (num + 7) / 8;
	
	if ((reg >= REG_D01) && (num > 0) && (reg + num <= REG_DXX + 1))
	{
		for (i = 0; i < m; i++)
		{
			status[i] = 0;
		}
		for (i = 0; i < num; i++)
		{
//			if (bsp_IsLedOn(i + 1 + reg - REG_D01))		/* 读LED的状态，写入状态寄存器的每一位 */
//			{  
//				status[i / 8] |= (1 << (i % 8));
//			}
		}
	}
	else
	{
		g_tModS.RspCode = RSP_ERR_REG_ADDR;				/* 寄存器地址错误 */
	}

	if (g_tModS.RspCode == RSP_OK)						/* 正确应答 */
	{
		g_tModS.TxCount = 0;
		g_tModS.TxBuf[g_tModS.TxCount++] = g_tModS.RxBuf[0];
		g_tModS.TxBuf[g_tModS.TxCount++] = g_tModS.RxBuf[1];
		g_tModS.TxBuf[g_tModS.TxCount++] = m;			/* 返回字节数 */

		for (i = 0; i < m; i++)
		{
			g_tModS.TxBuf[g_tModS.TxCount++] = status[i];	/* 继电器状态 */
		}
		MODS_SendWithCRC(g_tModS.TxBuf, g_tModS.TxCount);
	}
	else
	{
		MODS_SendAckErr(g_tModS.RspCode);				/* 告诉主机命令错误 */
	}
}

/*
*********************************************************************************************************
*	函 数 名: MODS_02H
*	功能说明: 读取输入状态（对应K01～K03）
*	形    参: 无
*	返 回 值: 无
*********************************************************************************************************
*/
static void MODS_02H(void)
{
	/*
		主机发送:
			11 从机地址
			02 功能码
			00 寄存器地址高字节
			C4 寄存器地址低字节
			00 寄存器数量高字节
			16 寄存器数量低字节
			BA CRC校验高字节
			A9 CRC校验低字节

		从机应答:  响应各离散输入寄存器状态，分别对应数据区中的每位值，1 代表ON；0 代表OFF。
		           第一个数据字节的LSB(最低字节)为查询的寻址地址，其他输入口按顺序在该字节中由低字节
		           向高字节排列，直到填充满8位。下一个字节中的8个输入位也是从低字节到高字节排列。
		           若返回的输入位数不是8的倍数，则在最后的数据字节中的剩余位至该字节的最高位使用0填充。
			11 从机地址
			02 功能码
			03 返回字节数
			AC 数据1(00C4H-00CBH)
			DB 数据2(00CCH-00D3H)
			35 数据3(00D4H-00D9H)
			20 CRC校验高字节
			18 CRC校验低字节

		例子:
		01 02 20 01 00 08  23CC  ---- 读取T01-08的状态
		01 02 20 04 00 02  B3CA  ---- 读取T04-05的状态
		01 02 20 01 00 12  A207   ---- 读 T01-18
	*/

	uint16_t reg;
	uint16_t num;
	uint16_t i;
	uint16_t m;
	uint8_t status[10];

	g_tModS.RspCode = RSP_OK;

	if (g_tModS.RxCount != 8)
	{
		g_tModS.RspCode = RSP_ERR_VALUE;				/* 数据值域错误 */
		return;
	}

	reg = BEBufToUint16(&g_tModS.RxBuf[2]); 			/* 寄存器号 */
	num = BEBufToUint16(&g_tModS.RxBuf[4]);				/* 寄存器个数 */

	m = (num + 7) / 8;
	if ((reg >= REG_T01) && (num > 0) && (reg + num <= REG_TXX + 1))
	{
		for (i = 0; i < m; i++)
		{
			status[i] = 0;
		}
		for (i = 0; i < num; i++)
		{
//			if (bsp_GetKeyState((KEY_ID_E)(KID_K1 + reg - REG_T01 + i)))
//			{
//				status[i / 8] |= (1 << (i % 8));
//			}
		}
	}
	else
	{
		g_tModS.RspCode = RSP_ERR_REG_ADDR;				/* 寄存器地址错误 */
	}

	if (g_tModS.RspCode == RSP_OK)						/* 正确应答 */
	{
		g_tModS.TxCount = 0;
		g_tModS.TxBuf[g_tModS.TxCount++] = g_tModS.RxBuf[0];
		g_tModS.TxBuf[g_tModS.TxCount++] = g_tModS.RxBuf[1];
		g_tModS.TxBuf[g_tModS.TxCount++] = m;			/* 返回字节数 */

		for (i = 0; i < m; i++)
		{
			g_tModS.TxBuf[g_tModS.TxCount++] = status[i];	/* T01-02状态 */
		}
		MODS_SendWithCRC(g_tModS.TxBuf, g_tModS.TxCount);
	}
	else
	{
		MODS_SendAckErr(g_tModS.RspCode);				/* 告诉主机命令错误 */
	}
}
/*
*********************************************************************************************************
*	函 数 名: AllMODS_ReadRegValue
*	功能说明: 读取保持寄存器的值，仅限广播读取
*	形    参: reg_addr 寄存器地址
*			  reg_value 存放寄存器结果
*	返 回 值: 1表示OK 0表示错误
*********************************************************************************************************
*/
static uint8_t AllMODS_ReadRegValue(uint16_t reg_addr, uint8_t *reg_value)
{
	uint16_t value;
	switch (reg_addr)							/* 判断寄存器地址 */
	{	
		//广播地址查询
		case 0x01:
			value = Sys.modbusAdd ;		/* 将值写入保存寄存器 */
			break;		
		default:
			return 0;		/* 参数异常，返回 0 */
	}

	reg_value[0] = value >> 8;
	reg_value[1] = value;

	return 1;											/* 读取成功 */
}
/*
*********************************************************************************************************
*	函 数 名: MODS_ReadRegValue
*	功能说明: 读取保持寄存器的值
*	形    参: reg_addr 寄存器地址
*			  reg_value 存放寄存器结果
*	返 回 值: 1表示OK 0表示错误
*********************************************************************************************************
*/
static uint8_t MODS_ReadRegValue(uint16_t reg_addr, uint8_t *reg_value)
{
	uint16_t	regADD = sizeof(ModbusReg)/3/2;
	//查找是否存在这个地址的寄存器
	while(regADD > 0)
	{
		regADD -- ;
		if(ModbusReg[regADD][RADD] == reg_addr)
		{
			break;
		}
		//判断完毕，回复失败状态
		if(regADD == 0)
		{
			return 0;			
		}
	}
	//判断是否可读,通过逻辑位运算判断，为0时不可读
	if((ModbusReg[regADD][RAW] & RO) == 0)
	{
		return 0;	
	}
	//进行读取数据
	reg_value[1] = (uint8_t)ModbusReg[regADD][RDATA] & 0x00ff;;
	reg_value[0] = (uint8_t)(ModbusReg[regADD][RDATA]>>8) & 0x00ff;;
	return 1;											/* 读取成功 */
}

/*
*********************************************************************************************************
*	函 数 名: MODS_WriteRegValue
*	功能说明: 写入保持寄存器的值
*	形    参: reg_addr 寄存器地址
*			  reg_value 寄存器值
*	返 回 值: 2需要外部处理 1表示OK 0表示错误
*********************************************************************************************************
*/
static uint8_t MODS_WriteRegValue(uint16_t reg_addr, uint16_t reg_value)
{
//	uint8_t valueL = (uint8_t)reg_value & 0x00ff;
//	uint8_t valueH = (uint8_t)(reg_value >> 8) & 0x00ff;
//	uint16_t value;
	

	uint16_t	regADD = sizeof(ModbusReg)/3/2;
	//查找是否存在这个地址的寄存器
	while(regADD > 0)
	{
		regADD -- ;
		if(ModbusReg[regADD][RADD] == reg_addr)
		{
			break;
		}
		//判断完毕，回复失败状态
		if(regADD == 0)
		{
			return 0;			
		}
	}
	//判断是否可写,通过逻辑位运算判断，为0时不可读
	if((ModbusReg[regADD][RAW] & WO) == 0)
	{
		return 0;	
	}
	//进行写入数据
	ModbusReg[regADD][RDATA]  = reg_value;
	return 1;											/* 写入成功 */
}
/*
*********************************************************************************************************
*	函 数 名: All_MODS_03H
*	功能说明: 读取保持寄存器 在一个或多个保持寄存器中取得当前的二进制值
*	形    参: 无
*	返 回 值: 无
*********************************************************************************************************
*/
static void All_MODS_03H(void)
{
	uint16_t reg;
	uint16_t num;
	uint16_t i;
	uint8_t reg_value[128];

	g_tModS.RspCode = RSP_OK;

	if (g_tModS.RxCount != 8)								/* 03H命令必须是8个字节 */
	{
		g_tModS.RspCode = RSP_ERR_VALUE;					/* 数据值域错误 */
		goto err_ret;
	}

	reg = BEBufToUint16(&g_tModS.RxBuf[2]); 				/* 寄存器号 */
	num = BEBufToUint16(&g_tModS.RxBuf[4]);					/* 寄存器个数 */
	if (num > sizeof(reg_value) / 2)
	{
		g_tModS.RspCode = RSP_ERR_VALUE;					/* 数据值域错误 */
		goto err_ret;
	}

	for (i = 0; i < num; i++)
	{
		if (AllMODS_ReadRegValue(reg, &reg_value[2 * i]) == 0)	/* 读出寄存器值放入reg_value */
		{
			g_tModS.RspCode = RSP_ERR_REG_ADDR;				/* 寄存器地址错误 */
			break;
		}
		reg++;
	}

err_ret:
	if (g_tModS.RspCode == RSP_OK)							/* 正确应答 */
	{
		g_tModS.TxCount = 0;
		g_tModS.TxBuf[g_tModS.TxCount++] = g_tModS.RxBuf[0];
		g_tModS.TxBuf[g_tModS.TxCount++] = g_tModS.RxBuf[1];
		g_tModS.TxBuf[g_tModS.TxCount++] = num * 2;			/* 返回字节数 */

		for (i = 0; i < num; i++)
		{
			g_tModS.TxBuf[g_tModS.TxCount++] = reg_value[2*i];
			g_tModS.TxBuf[g_tModS.TxCount++] = reg_value[2*i+1];
		}
		MODS_SendWithCRC(g_tModS.TxBuf, g_tModS.TxCount);	/* 发送正确应答 */
	}
	else
	{
		MODS_SendAckErr(g_tModS.RspCode);					/* 发送错误应答 */
	}
}
/*
*********************************************************************************************************
*	函 数 名: MODS_03H
*	功能说明: 读取保持寄存器 在一个或多个保持寄存器中取得当前的二进制值
*	形    参: 无
*	返 回 值: 无
*********************************************************************************************************
*/
static void MODS_03H(void)
{
	uint16_t reg;
	uint16_t num;
	uint16_t i;
	uint8_t reg_value[256];

	g_tModS.RspCode = RSP_OK;

	if (g_tModS.RxCount != 8)								/* 03H命令必须是6个字节 */
	{
		g_tModS.RspCode = RSP_ERR_VALUE;					/* 数据值域错误 */
		goto err_ret;
	}

	reg = BEBufToUint16(&g_tModS.RxBuf[2]); 				/* 寄存器号 */
	num = BEBufToUint16(&g_tModS.RxBuf[4]);					/* 寄存器个数 */
	if (num > sizeof(reg_value) / 2)
	{
		g_tModS.RspCode = RSP_ERR_VALUE;					/* 数据值域错误 */
		goto err_ret;
	}

	for (i = 0; i < num; i++)
	{
		if (MODS_ReadRegValue(reg, &reg_value[2 * i]) == 0)	/* 读出寄存器值放入reg_value */
		{
			g_tModS.RspCode = RSP_ERR_REG_ADDR;				/* 寄存器地址错误 */
			break;
		}
		reg++;
	}

err_ret:
	if (g_tModS.RspCode == RSP_OK)							/* 正确应答 */
	{
		g_tModS.TxCount = 0;
		g_tModS.TxBuf[g_tModS.TxCount++] = g_tModS.RxBuf[0];
		g_tModS.TxBuf[g_tModS.TxCount++] = g_tModS.RxBuf[1];
		g_tModS.TxBuf[g_tModS.TxCount++] = num * 2;			/* 返回字节数 */

		for (i = 0; i < num; i++)
		{
			g_tModS.TxBuf[g_tModS.TxCount++] = reg_value[2*i];
			g_tModS.TxBuf[g_tModS.TxCount++] = reg_value[2*i+1];
		}
		MODS_SendWithCRC(g_tModS.TxBuf, g_tModS.TxCount);	/* 发送正确应答 */
	}
	else
	{
		MODS_SendAckErr(g_tModS.RspCode);					/* 发送错误应答 */
	}
}


/*
*********************************************************************************************************
*	函 数 名: MODS_04H
*	功能说明: 读取输入寄存器（对应A01/A02） SMA
*	形    参: 无
*	返 回 值: 无
*********************************************************************************************************
*/
static void MODS_41H(void)
{

//	uint16_t reg;
//	uint16_t num;
//	uint16_t i;
	
	//必须是16个,必须有那么多数据才可以
	if((g_tModS.RxBuf[3] != 0x10)&&(g_tModS.RxCount >= 20))
	{
		g_tModS.RspCode = g_tModS.RxBuf[1];
		goto err_ret;
	}
	//确定写入区域
	if((g_tModS.RxBuf[2] == 0x01)|(g_tModS.RxBuf[2]== 0x02))
	{
//		MainPar.writeStartAdd = ((g_tModS.RxBuf[2]-1)*4)+1;
//		MainPar.writeLen = 1;
	}
	else 
	{
		g_tModS.RspCode = g_tModS.RxBuf[1];
		goto err_ret;
	}
	
//	memcpy(MainPar.writeDataOUT,&g_tModS.RxBuf[4],0x10);
	
//	if(RFID_write()== 0x01)
//	{	
//		g_tModS.RspCode = RSP_OK;
//	}
//	else
//	{
//		g_tModS.RspCode = RSP_NOTCARR;
//	}
	
err_ret:
	if (g_tModS.RspCode == RSP_OK)		/* 正确应答 */
	{
		g_tModS.TxCount = 0;
		g_tModS.TxBuf[g_tModS.TxCount++] = g_tModS.RxBuf[0];
		g_tModS.TxBuf[g_tModS.TxCount++] = g_tModS.RxBuf[1];
		g_tModS.TxBuf[g_tModS.TxCount++] = 0X4F;			
		g_tModS.TxBuf[g_tModS.TxCount++] = 0X4B;	

		MODS_SendWithCRC(g_tModS.TxBuf, g_tModS.TxCount);
	}
	else if(g_tModS.RspCode == RSP_NOTCARR)
	{
		g_tModS.TxCount = 0;
		g_tModS.TxBuf[g_tModS.TxCount++] = g_tModS.RxBuf[0];
		g_tModS.TxBuf[g_tModS.TxCount++] = g_tModS.RxBuf[1];
		g_tModS.TxBuf[g_tModS.TxCount++] = 0x45;
		g_tModS.TxBuf[g_tModS.TxCount++] = 0x30;
		g_tModS.TxBuf[g_tModS.TxCount++] = 0x31;

		MODS_SendWithCRC(g_tModS.TxBuf, g_tModS.TxCount);
	}
	else
	{
		g_tModS.TxCount = 0;
		g_tModS.TxBuf[g_tModS.TxCount++] = g_tModS.RxBuf[0];
		g_tModS.TxBuf[g_tModS.TxCount++] = g_tModS.RxBuf[1];
		g_tModS.TxBuf[g_tModS.TxCount++] = 0x45;
		g_tModS.TxBuf[g_tModS.TxCount++] = 0x30;
		g_tModS.TxBuf[g_tModS.TxCount++] = 0x32;

		MODS_SendWithCRC(g_tModS.TxBuf, g_tModS.TxCount);
	}
}

/*
*********************************************************************************************************
*	函 数 名: MODS_04H
*	功能说明: 读取输入寄存器（对应A01/A02） SMA
*	形    参: 无
*	返 回 值: 无
*********************************************************************************************************
*/
static void MODS_42H(void)
{

//	uint16_t reg;
//	uint16_t num;
//	uint16_t i;
//	uint8_t status[20];

//	memset(status, 0x00, 20);
	;
//	//是否有卡
//	if(MainPar.ReadStatus == false)
//	{
//		g_tModS.RspCode = RSP_NOTCARR;
//		goto err_ret;
//	}
//	//开始获取数据
//	if((g_tModS.RxBuf[2] == 0x01)|(g_tModS.RxBuf[2] == 0x02))
//	{
//		g_tModS.TxCount = 0;
//		g_tModS.TxBuf[g_tModS.TxCount++] = g_tModS.RxBuf[0];
//		g_tModS.TxBuf[g_tModS.TxCount++] = g_tModS.RxBuf[1];
//		memcpy(&g_tModS.TxBuf[g_tModS.TxCount],status,16);
//		g_tModS.TxCount +=  16;
//		
//		MODS_SendWithCRC(g_tModS.TxBuf, g_tModS.TxCount);
//	}
//	else if(g_tModS.RspCode == RSP_NOTCARR)
//	{
//		g_tModS.TxCount = 0;
//		g_tModS.TxBuf[g_tModS.TxCount++] = g_tModS.RxBuf[0];
//		g_tModS.TxBuf[g_tModS.TxCount++] = g_tModS.RxBuf[1];
//		g_tModS.TxBuf[g_tModS.TxCount++] = 0x45;
//		g_tModS.TxBuf[g_tModS.TxCount++] = 0x30;
//		g_tModS.TxBuf[g_tModS.TxCount++] = 0x31;

//		MODS_SendWithCRC(g_tModS.TxBuf, g_tModS.TxCount);
//	}
//	else
//	{
//		g_tModS.TxCount = 0;
//		g_tModS.TxBuf[g_tModS.TxCount++] = g_tModS.RxBuf[0];
//		g_tModS.TxBuf[g_tModS.TxCount++] = g_tModS.RxBuf[1];
//		g_tModS.TxBuf[g_tModS.TxCount++] = 0x45;
//		g_tModS.TxBuf[g_tModS.TxCount++] = 0x30;
//		g_tModS.TxBuf[g_tModS.TxCount++] = 0x32;

//		MODS_SendWithCRC(g_tModS.TxBuf, g_tModS.TxCount);
//	}
}

/*
*********************************************************************************************************
*	函 数 名: MODS_04H
*	功能说明: 读取输入寄存器（对应A01/A02） SMA
*	形    参: 无
*	返 回 值: 无
*********************************************************************************************************
*/
static void MODS_43H(void)
{

	uint16_t reg;
	uint16_t num;
	uint16_t i;
//	uint16_t status[10];

//	memset(status, 0, 10);

	g_tModS.RspCode = RSP_OK;
	
	//关灯
	if(g_tModS.RxBuf[2] == 0x02)
	{
	printf("LED OFF.\r\n");
	}
	
	//开灯状态控制
	else if(g_tModS.RxBuf[2] == 0x01)
	{
		if(g_tModS.RxBuf[3] != 0x01)
			{
			g_tModS.RspCode = g_tModS.RxBuf[1];
			goto err_ret;
			}
		g_tModS.RspCode = RSP_OK;
//		if(MainPar.ReadStatus == true)
//		{
//			switch(g_tModS.RxBuf[4])
//				{
//				case 0x01://红灯

//				default:	
//					g_tModS.RspCode =g_tModS.RxBuf[1];
//					goto err_ret;
//				break;
//			}
//		}
	}
	//LED参数配置
	else if(g_tModS.RxBuf[2] == 0x03)
	{
		if((g_tModS.RxBuf[3] >=1)&&(g_tModS.RxBuf[3] <= 100))
		{
			g_tModS.RspCode = RSP_OK;
//			Sys.led_lum = g_tModS.RxBuf[3];
//			printf("Sys.led_lum:%d\r\n",Sys.led_lum);
			//保存到FLASH中
//			Sys_Save();
		}
		else 
		{
			//数据值域错误
			g_tModS.RspCode = RSP_ERR_VALUE;
			goto err_ret;
		}
	}


err_ret:
	if (g_tModS.RspCode == RSP_OK)		/* 正确应答 */
	{
		g_tModS.TxCount = 0;
		g_tModS.TxBuf[g_tModS.TxCount++] = g_tModS.RxBuf[0];
		g_tModS.TxBuf[g_tModS.TxCount++] = g_tModS.RxBuf[1];
		g_tModS.TxBuf[g_tModS.TxCount++] = 0X4F;			
		g_tModS.TxBuf[g_tModS.TxCount++] = 0X4B;			
		
		MODS_SendWithCRC(g_tModS.TxBuf, g_tModS.TxCount);
	}
	else
	{
		g_tModS.TxCount = 0;
		g_tModS.TxBuf[g_tModS.TxCount++] = g_tModS.RxBuf[0];
		g_tModS.TxBuf[g_tModS.TxCount++] = g_tModS.RxBuf[1];
		g_tModS.TxBuf[g_tModS.TxCount++] = 0x45;
		g_tModS.TxBuf[g_tModS.TxCount++] = 0x30;
		g_tModS.TxBuf[g_tModS.TxCount++] = 0x32;

		MODS_SendWithCRC(g_tModS.TxBuf, g_tModS.TxCount);
	}
}

/*
*********************************************************************************************************
*	函 数 名: MODS_04H
*	功能说明: 读取输入寄存器（对应A01/A02） SMA
*	形    参: 无
*	返 回 值: 无
*********************************************************************************************************
*/
static void MODS_47H(void)
{
	/*
		主机发送:
			11 从机地址
			04 功能码
			00 寄存器起始地址高字节
			08 寄存器起始地址低字节
			00 寄存器个数高字节
			02 寄存器个数低字节
			F2 CRC高字节
			99 CRC低字节

		从机应答:  输入寄存器长度为2个字节。对于单个输入寄存器而言，寄存器高字节数据先被传输，
				低字节数据后被传输。输入寄存器之间，低地址寄存器先被传输，高地址寄存器后被传输。
			11 从机地址
			04 功能码
			04 字节数
			00 数据1高字节(0008H)
			0A 数据1低字节(0008H)
			00 数据2高字节(0009H)
			0B 数据2低字节(0009H)
			8B CRC高字节
			80 CRC低字节

		例子:

			01 04 2201 0006 2BB0  --- 读 2201H A01通道模拟量 开始的6个数据
			01 04 2201 0001 6A72  --- 读 2201H
			
			01 04 04 01 00 08 A1 3C //读取多个参数
			01 04 10 00 11 00 12 00 13 00 14 00 15 00 16 00 17 00 18 A4 7A //返回多个数据
	*/
	uint16_t reg;
	uint16_t num;
	uint16_t i;
//	uint16_t status[10];

//	memset(status, 0, 10);

	
	//查询设备地址并返回
	if(g_tModS.RxBuf[2] == 0x01)
	{
		if(g_tModS.RxBuf[3] == 0x06)
		{
			g_tModS.RspCode = RSP_OK;
		}
		else {g_tModS.RspCode = g_tModS.RxBuf[1];goto err_ret;}
	}
	else {g_tModS.RspCode = g_tModS.RxBuf[1];goto err_ret;}

	
err_ret:
	if (g_tModS.RspCode == RSP_OK)		/* 正确应答 */
	{
		g_tModS.TxCount = 0;
		g_tModS.TxBuf[g_tModS.TxCount++] = g_tModS.RxBuf[0];
		g_tModS.TxBuf[g_tModS.TxCount++] = g_tModS.RxBuf[1];
		g_tModS.TxBuf[g_tModS.TxCount++] = Sys.modbusAdd;					
		
		MODS_SendWithCRC(g_tModS.TxBuf, g_tModS.TxCount);
	}
	else
	{
		MODS_SendAckErr(g_tModS.RspCode);	/* 告诉主机命令错误 */
	}
}
/*
*********************************************************************************************************
*	函 数 名: MODS_04H
*	功能说明: 读取输入寄存器（对应A01/A02） SMA
*	形    参: 无
*	返 回 值: 无
*********************************************************************************************************
*/
static void MODS_04H(void)
{
	/*
		主机发送:
			11 从机地址
			04 功能码
			00 寄存器起始地址高字节
			08 寄存器起始地址低字节
			00 寄存器个数高字节
			02 寄存器个数低字节
			F2 CRC高字节
			99 CRC低字节

		从机应答:  输入寄存器长度为2个字节。对于单个输入寄存器而言，寄存器高字节数据先被传输，
				低字节数据后被传输。输入寄存器之间，低地址寄存器先被传输，高地址寄存器后被传输。
			11 从机地址
			04 功能码
			04 字节数
			00 数据1高字节(0008H)
			0A 数据1低字节(0008H)
			00 数据2高字节(0009H)
			0B 数据2低字节(0009H)
			8B CRC高字节
			80 CRC低字节

		例子:

			01 04 2201 0006 2BB0  --- 读 2201H A01通道模拟量 开始的6个数据
			01 04 2201 0001 6A72  --- 读 2201H
			
			01 04 04 01 00 08 A1 3C //读取多个参数
			01 04 10 00 11 00 12 00 13 00 14 00 15 00 16 00 17 00 18 A4 7A //返回多个数据
	*/
	uint16_t reg;
	uint16_t num;
	uint16_t i;
	uint16_t status[10];

	memset(status, 0, 10);

	g_tModS.RspCode = RSP_OK;

	if (g_tModS.RxCount != 8)
	{
		g_tModS.RspCode = RSP_ERR_VALUE;	/* 数据值域错误 */
		goto err_ret;
	}

	reg = BEBufToUint16(&g_tModS.RxBuf[2]); 	/* 寄存器号 */
	num = BEBufToUint16(&g_tModS.RxBuf[4]);	/* 寄存器个数 */
	
//	if ((reg >= NFC15693_DATA_1) && (num > 0) && (reg + num <= NFC15693_DATA_8 + 1))
//	{	
//		for (i = 0; i < num; i++)
//		{
//			switch (reg)
//			{
//				case NFC15693_DATA_1:
//					status[i] = MainPar.ReadData[0];
//				break;	
//				case NFC15693_DATA_2:
//					status[i] = MainPar.ReadData[1];
//				break;
//				case NFC15693_DATA_3:
//					status[i] = MainPar.ReadData[2];
//				break;	
//				case NFC15693_DATA_4:
//					status[i] = MainPar.ReadData[3];
//				break;
//				case NFC15693_DATA_5:
//					status[i] = MainPar.ReadData[4];
//				break;	
//				case NFC15693_DATA_6:
//					status[i] = MainPar.ReadData[5];
//				break;
//				
//				case NFC15693_DATA_7:
//					status[i] = MainPar.ReadData[6];
//				break;	
//				case NFC15693_DATA_8:
//					status[i] = MainPar.ReadData[7];
//				break;
//					
//				default:
//					status[i] = 0;
//					break;
//			}
//			reg++;
//		}
//	}
//	else
//	{
//		g_tModS.RspCode = RSP_ERR_REG_ADDR;		/* 寄存器地址错误 */
//	}

err_ret:
	if (g_tModS.RspCode == RSP_OK)		/* 正确应答 */
	{
		g_tModS.TxCount = 0;
		g_tModS.TxBuf[g_tModS.TxCount++] = g_tModS.RxBuf[0];
		g_tModS.TxBuf[g_tModS.TxCount++] = g_tModS.RxBuf[1];
		g_tModS.TxBuf[g_tModS.TxCount++] = num * 2;			/* 返回字节数 */

		for (i = 0; i < num; i++)
		{
			g_tModS.TxBuf[g_tModS.TxCount++] = status[i] >> 8;
			g_tModS.TxBuf[g_tModS.TxCount++] = status[i] & 0xFF;
		}
		MODS_SendWithCRC(g_tModS.TxBuf, g_tModS.TxCount);
	}
	else
	{
		MODS_SendAckErr(g_tModS.RspCode);	/* 告诉主机命令错误 */
	}
}

/*
*********************************************************************************************************
*	函 数 名: MODS_05H
*	功能说明: 强制单线圈（对应D01/D02/D03）
*	形    参: 无
*	返 回 值: 无
*********************************************************************************************************
*/
static void MODS_05H(void)
{
	/*
		主机发送: 写单个线圈寄存器。FF00H值请求线圈处于ON状态，0000H值请求线圈处于OFF状态
		。05H指令设置单个线圈的状态，15H指令可以设置多个线圈的状态。
			11 从机地址
			05 功能码
			00 寄存器地址高字节
			AC 寄存器地址低字节
			FF 数据1高字节
			00 数据2低字节
			4E CRC校验高字节
			8B CRC校验低字节

		从机应答:
			11 从机地址
			05 功能码
			00 寄存器地址高字节
			AC 寄存器地址低字节
			FF 寄存器1高字节
			00 寄存器1低字节
			4E CRC校验高字节
			8B CRC校验低字节

		例子:
		01 05 10 01 FF 00   D93A   -- D01打开
		01 05 10 01 00 00   98CA   -- D01关闭

		01 05 10 02 FF 00   293A   -- D02打开
		01 05 10 02 00 00   68CA   -- D02关闭

		01 05 10 03 FF 00   78FA   -- D03打开
		01 05 10 03 00 00   390A   -- D03关闭
		
		//例子
		01 05 00 01 00 00 9C 0A //关闭红灯
		01 05 00 01 00 01 5D CA //打开红灯
		
		01 05 00 02 00 00 6C 0A //关闭绿灯
		01 05 00 02 00 01 AD CA //打开绿灯
		
	*/
	uint16_t reg;
	uint16_t value;

	g_tModS.RspCode = RSP_OK;
	//必须为8个字节
	if (g_tModS.RxCount != 8)
	{
		g_tModS.RspCode = RSP_ERR_VALUE;		/* 数据值域错误 */
		goto err_ret;
	}
	//确定要写入的寄存器号
	reg = BEBufToUint16(&g_tModS.RxBuf[2]); 	/* 寄存器号 */
	//要写入的数据
	value = BEBufToUint16(&g_tModS.RxBuf[4]);	/* 数据 */
	
	if (value != 0 && value != 1)
	{
		g_tModS.RspCode = RSP_ERR_VALUE;		/* 数据值域错误 */
		goto err_ret;
	}
	
	if (reg == REG_D01)
	{
	}
	else if (reg == REG_D02)
	{
	}
	else
	{
		g_tModS.RspCode = RSP_ERR_REG_ADDR;		/* 寄存器地址错误 */
	}
err_ret:
	if (g_tModS.RspCode == RSP_OK)				/* 正确应答 */
	{
		MODS_SendAckOk();
	}
	else
	{
		MODS_SendAckErr(g_tModS.RspCode);		/* 告诉主机命令错误 */
	}
}

/*
*********************************************************************************************************
*	函 数 名: MODS_06H
*	功能说明: 写单个寄存器
*	形    参: 无
*	返 回 值: 无
*********************************************************************************************************
*/
static void MODS_06H(void)
{

	/*
		写保持寄存器。注意06指令只能操作单个保持寄存器，16指令可以设置单个或多个保持寄存器

		主机发送:
			11 从机地址
			06 功能码
			00 寄存器地址高字节
			01 寄存器地址低字节
			00 数据1高字节
			01 数据1低字节
			9A CRC校验高字节
			9B CRC校验低字节

		从机响应:
			11 从机地址
			06 功能码
			00 寄存器地址高字节
			01 寄存器地址低字节
			00 数据1高字节
			01 数据1低字节
			1B CRC校验高字节
			5A	CRC校验低字节

		例子:
			01 06 30 06 00 25  A710    ---- 触发电流设置为 2.5
			01 06 30 06 00 10  6707    ---- 触发电流设置为 1.0


			01 06 30 1B 00 00  F6CD    ---- SMA 滤波系数 = 0 关闭滤波
			01 06 30 1B 00 01  370D    ---- SMA 滤波系数 = 1
			01 06 30 1B 00 02  770C    ---- SMA 滤波系数 = 2
			01 06 30 1B 00 05  36CE    ---- SMA 滤波系数 = 5

			01 06 30 07 00 01  F6CB    ---- 测试模式修改为 T1
			01 06 30 07 00 02  B6CA    ---- 测试模式修改为 T2

			01 06 31 00 00 00  8736    ---- 擦除浪涌记录区
			01 06 31 01 00 00  D6F6    ---- 擦除告警记录区

*/

	uint16_t reg;
	uint16_t value;

	g_tModS.RspCode = RSP_OK;

	if (g_tModS.RxCount != 8)
	{
		g_tModS.RspCode = RSP_ERR_VALUE;		/* 数据值域错误 */
		goto err_ret;
	}

	reg = BEBufToUint16(&g_tModS.RxBuf[2]); 	/* 寄存器号 */
	value = BEBufToUint16(&g_tModS.RxBuf[4]);	/* 寄存器值 */

	if (MODS_WriteRegValue(reg, value) == 1)	/* 该函数会把写入的值存入寄存器 */
	{
		;
	}
	else
	{
		g_tModS.RspCode = RSP_ERR_REG_ADDR;		/* 寄存器地址错误 */
	}

err_ret:
	if (g_tModS.RspCode == RSP_OK)				/* 正确应答 */
	{
		MODS_SendAckOk();
	}
	else
	{
		MODS_SendAckErr(g_tModS.RspCode);		/* 告诉主机命令错误 */
	}
}

/*
*********************************************************************************************************
*	函 数 名: MODS_10H
*	功能说明: 连续写多个寄存器.  
*	形    参: 无
*	返 回 值: 无
*********************************************************************************************************
*/
static void MODS_10H(void)
{
	/*
		从机地址为11H。保持寄存器的其实地址为0001H，寄存器的结束地址为0002H。总共访问2个寄存器。
		保持寄存器0001H的内容为000AH，保持寄存器0002H的内容为0102H。

		主机发送:
			11 从机地址
			10 功能码
			00 寄存器起始地址高字节
			01 寄存器起始地址低字节
			00 寄存器数量高字节
			02 寄存器数量低字节
			04 字节数
			00 数据1高字节
			0A 数据1低字节
			01 数据2高字节
			02 数据2低字节
			C6 CRC校验高字节
			F0 CRC校验低字节

		从机响应:
			11 从机地址
			06 功能码
			00 寄存器地址高字节
			01 寄存器地址低字节
			00 数据1高字节
			01 数据1低字节
			1B CRC校验高字节
			5A	CRC校验低字节

		例子:
			01 10 30 00 00 06 0C  07 DE  00 0A  00 01  00 08  00 0C  00 00     389A    ---- 写时钟 2014-10-01 08:12:00
			01 10 30 00 00 06 0C  07 DF  00 01  00 1F  00 17  00 3B  00 39     5549    ---- 写时钟 2015-01-31 23:59:57

	*/
	uint16_t reg_addr;
	uint16_t reg_num;
	uint8_t byte_num;
	uint8_t i;
	uint16_t value;
	uint8_t writeState = 0 ;
	
	g_tModS.RspCode = RSP_OK;

	if (g_tModS.RxCount < 9)
	{
		g_tModS.RspCode = RSP_ERR_VALUE;			/* 数据值域错误 */
		goto err_ret;
	}

	reg_addr = BEBufToUint16(&g_tModS.RxBuf[2]); 	/* 寄存器号 */
	reg_num = BEBufToUint16(&g_tModS.RxBuf[4]);		/* 寄存器个数 */
	byte_num = g_tModS.RxBuf[6];					/* 后面的数据体字节数 */

	if (byte_num != 2 * reg_num)
	{
		;
	}
	
	for (i = 0; i < reg_num; i++)
	{
		value = BEBufToUint16(&g_tModS.RxBuf[7 + 2 * i]);	/* 寄存器值 */

		writeState = MODS_WriteRegValue(reg_addr + i, value);
		//完成写入
		if (writeState == 1)
		{
			;
		}
		//有写卡操作，需要外部支持
		//在写卡外部后，会进行使用
		else if( writeState == 2 )
		{
			;
		}
		else
		{
			g_tModS.RspCode = RSP_ERR_REG_ADDR;		/* 寄存器地址错误 */
			break;
		}
	}
	//如果需要写入进行进行标签
//	if(writeState == 2 ){
//		if(RFID_write()== 0x01)
//		{	
//			g_tModS.RspCode = RSP_OK;
//		}
//		else
//		{
//			g_tModS.RspCode = RSP_ERR_WRITE;
//		}
//	}
err_ret:
	if (g_tModS.RspCode == RSP_OK)					/* 正确应答 */
	{
		MODS_SendAckOk();
	}
	else
	{
		MODS_SendAckErr(g_tModS.RspCode);			/* 告诉主机命令错误 */
	}
}

//获取对应MODBUS寄存器的值
int16_t reafMdodbusReg(int16_t reg)
{
	return ModbusReg[reg][RDATA];
}

//设置对应MODBUS寄存器的值
void writeMdodbusReg(uint16_t reg,int16_t value)
{
	ModbusReg[reg][RDATA] = value;
	
	//如果是功率寄存器，就需要进行更新功率
//	if(reg == MReg_Power){mainPar.RfPaupdeta = 1;}
}
